
module lcc$render {

const {ccclass, property, executeInEditMode} = cc._decorator;

/**
 * 宏配置
 */
@ccclass("lcc$render.MacroConfig")
export class MacroConfig {
	@property({
		tooltip : "宏名称(为空表示不启用)"
	})
	name:string = "";

	@property({
		tooltip : "只用于检查"
	})
	checkOnly:boolean = false;

	constructor(...params:any){
		this.name = params[0] || "";
		this.checkOnly = params[1] || false;
	}
}

/**
 * 着色器变量
 */
export enum VariableType {
	/**
	 * 属性
	 */
	ATTRIBUTE = 1,

	/**
	 * 一般变量
	 */
	UNIFORM,
};

/**
 * 值类型
 */
export enum ValueType {
	/**
	 * 单
	 */
	SINGLE,

	/**
	 * 数组
	 */
	ARRAY,
};

/**
 * 变量配置
 */
@ccclass("lcc$render.VariableConfig")
export class VariableConfig {
	@property()
	_typesel:boolean = true;

	@property({
		type : cc.Enum(VariableType),
		tooltip : "变量类型",
		visible (){
			return this._typesel;
		}
	})
	type:VariableType = VariableType.UNIFORM;

	@property({
		type : MacroConfig,
		tooltip : "属性变量宏定义",
		visible (){
			return this.type == VariableType.ATTRIBUTE;
		}
	})
	attrMacro:MacroConfig = new MacroConfig();

	@property({
		tooltip : "属性变量名",
		visible (){
			return this.type == VariableType.ATTRIBUTE;
		}
	})
	attrName:string = "";

	@property({
		type : MacroConfig,
		tooltip : "一般变量宏定义",
		visible (){
			return this.type == VariableType.UNIFORM;
		}
	})
	unifMacro:MacroConfig = new MacroConfig();

	@property({
		tooltip : "一般变量名",
		visible (){
			return this.type == VariableType.UNIFORM;
		}
	})
	unifName:string = "";

	constructor(...params:any){
		this._typesel = params[0];
		this.type = params[1] || VariableType.UNIFORM;
		this.attrMacro = new MacroConfig(params[2] || "", params[3] || false);
		this.attrName = params[4] || "";
		this.unifMacro = new MacroConfig(params[5] || "", params[6] || false);
		this.unifName = params[7] || "";
	}
}

@ccclass("lcc$render.ShaderComponent")
@executeInEditMode()
export class ShaderComponent extends cc.Component {
	
	@property()
	_tag:string = "";
	@property({
		tooltip : "组件标签"
	})
	get tag(){
		return this._tag;
	}
	set tag(value:string){
		if(this._tag != value){
			this._tag = value;
			this.node.emit("shader_update_tag");
		}
	}

	/**
	 * 检查材质中的宏
	 * @param material 
	 * @param macro 
	 */
	protected checkMaterialMacro(material:cc.Material, macro:MacroConfig){
		return !macro.name || (macro.checkOnly ? material.getDefine(macro.name) : 
			(material.getDefine(macro.name) !== undefined));
	}
	
	/**
	 * 定义材质中的宏
	 * @param material 
	 * @param macro 
	 * @param value 
	 */
	protected defineMaterialMacro(material:cc.Material, macro:MacroConfig, value:number|boolean){
		if(macro.name && !macro.checkOnly){
			material.define(macro.name, value);
		}
	}
	
	/**
	 * 获得着色器组件
	 * @param type 
	 * @param tag 
	 */
	protected getShaderComponent<T extends ShaderComponent>(type: {prototype: T}, tag?:string){
		if(tag === undefined){
			return this.getComponent(type);
		}else{
			for(let comp of this.getComponents(type)){
				if(comp._tag == tag){
					return comp;
				}
			}
		}
	}
	
	/**
	 * 获得着色器组件数组
	 * @param type 
	 * @param tag 
	 */
	protected getShaderComponents<T extends ShaderComponent>(type: {prototype: T}, tag?:string){
		if(tag === undefined){
			return this.getComponents(type);
		}else{
			let comps = this.getComponents(type);
			return comps.filter((a)=>{ a._tag == tag; });
		}
	}
}

}
